home *** CD-ROM | disk | FTP | other *** search
- *****Listing 3*****
-
- /* cmd_opts.c, c\lib\src, (c) 1989 Scott D. Maley
- May be freely used, as long as copyright notice is preserved
-
- cmd_options(argc, argv, option)
-
- int *argc; -- pointer to command line arg count
- char *argv[]; -- pointer to array of pointers to
- command line arguments
- struct options option[]; -- structure array defining valid
- options
-
- This is a function to process command line options (or
- switches). The full set of command line arguments is passed
- to the routine via argc and argv. Every option switch
- encountered that is a valid match for a switch specified in
- the option array is counted, removed from argv, and the
- pointer to it's associated value (if any) is moved to
- the optv array. A count of switches which are not valid
- matches of any option is returned, and those switches are
- left in argv.
-
- A switch's value may be contiguous with it, or be separated
- from it by white-space (e.g. -svalue, -s value). White-
- space is commonly blanks and tabs, but may also include
- commas in some C implementations. This routine doesn't care.
- The C runtime initilization routine which runs before main()
- is entered parses the command line into tokens (which the
- elements of argv point to), based on it's definition of
- white-space.
-
- The structure "options" is used to define what this routine
- will parse:
-
- struct options
- {
- char s; -- The option (switch) letter
- int arg_flg; -- indicates if an arg is required
- char **poptv[];-- pointer to option value vector
- -- NULL, if none expected
- } ;
-
- The third argument to this routine, option, is an array of
- the options structures. The end of this array is signaled
- with s == 0.
-
- This routine returns:
- 0 - if all switches encountered were valid options.
- -n - Negative of the count of invalid (e.g. no
- value followed the switch when one was expected, or
- a value was contiguous with the switch, but none
- was expected) switches encountered. N also includes
- a count of switches that were expected, but not
- encountered in argv.
-
- It also sets arg_flg to indicate how many of each
- switch encountered.
-
-
- Sample use:
- ----------
-
- #include <stdio.h>
- #include "cmd_opts.h"
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- char s, *farg[] *marg[];
- static struct options sw[] =
- {'a', 0, NULL, -- optional, no value
- 'f', 0, &farg, -- optional, w/ value
- 'm', 1, &marg, -- required, w/ value
- 0, 0, NULL};
-
- if (cmd_options( & argc, argv, sw) < 0)
- {
- --- error, handle it here
- ---
- }
- ---
- --- continue with rest of program
- ---
- }
-
- *-- History:
- * 30 Jan 89 SDM (TASC) No need to calloc optv, we
- * can work entirely within argv (plus
- * a temp pointer).
- * 27 Jan 89 SDM (TASC) Handle multiple instances
- * of a switch.
- * Retain everything not
- * specified in opts in argv, and set
- * argc accordingly.
- * 20 Jan 89 S.D. Maley (TASC) Initial implementation.
- *-- End History
- */
-
- #include <stdio.h>
- #include "cmd_opts.h"
-
-
- #define EOS '\0'
-
- #define MoveOptFromArg(optv,argv,i,argc) \
- {char *temp;\
- temp= argv[i];\
- RemoveArg(argv,i,argc);\
- (optv)--;\
- optv[0]= temp;\
- }
-
- #define RemoveArg(argv,i,argc) \
- {int j;\
- (argc)--;\
- for(j=i;j<argc;j++) argv[j]=argv[j+1];\
- }
-
- #define SWFLG '-'
- #define SwChr *(argv[i]+1)
- #define SwMatch (*argv[i] == SWFLG && opts[j].s == SwChr)
- #define SwValContig (*(argv[i]+2) != EOS)
- #define SwValNext (i+1 < *argc && *argv[i+1] != SWFLG)
-
-
- cmd_options(argc, argv, opts)
- int *argc;
- char *argv[];
- struct options opts[];
- {
- int i,j, njth, stat;
- char **optv; /* equivalent to: *optv[] */
-
- optv = argv + *argc; /* work from back to front */
-
- /*-- Transfer options from argv to optv
- * -- and check against expectations
- */
- stat = 0;
-
- for (j = 0; opts[j].s != 0; j++)
- {
- njth = 0;
-
- for (i = *argc - 1; i > 0; i--)
- { /* back to front, we build optv */
- if (SwMatch)
- {
- if (opts[j].poptv == NULL)
- { /* no arg value desired */
- if (SwValContig)
- continue; /* next i */
- else
- RemoveArg(argv,i,*argc);
- } else { /* A value is desired */
- if (SwValContig)
- {
- argv[i] += 2; /* past "-'opt_char'" */
- MoveOptFromArg(optv, argv,i,*argc);
- } else if (SwValNext)
- { /*-- pick up value from next arg */
- RemoveArg(argv,i,*argc);
- MoveOptFromArg(optv, argv,i,*argc);
- } else
- continue; /* next i */
- }
- njth++; /* only count valid switches */
- } /* if SwMatch */
- } /* for i */
-
- if (opts[j].poptv != NULL)
- *opts[j].poptv= optv; /* point to option value vector */
- if (opts[j].arg_flg > njth )
- stat -= opts[j].arg_flg - njth ; /* not enough */
- opts[j].arg_flg = njth;
-
- } /* for j */
-
- for (i= 1; i < *argc; i++)
- if (*argv[i] == SWFLG)
- stat--; /* a switch we couldn't handle */
- return(stat);
- }
-